home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 28
/
Aminet 28 (1998)(GTI - Schatztruhe)[!][Dec 1998].iso
/
Aminet
/
dev
/
lang
/
fpcsrc.lha
/
fpc
/
compiler
/
link.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1998-09-24
|
16KB
|
540 lines
{
$Id: link.pas,v 1.2.2.4 1998/08/31 12:19:29 peter Exp $
Copyright (c) 1998 by the FPC development team
This unit handles the linker and binder calls for programs and
libraries
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
****************************************************************************
}
Unit link;
Interface
uses cobjects;
Type TLinker = Object
{ Internal variables. Don't access directly }
{$ifdef linux}
LinkToC : Boolean; { Should we link to the C libs? }
GccLibraryPath : String; { Where is GCCLIB ? }
DynamicLinker : String; { What Dynamic linker ? }
{$endif}
OFiles, LibFiles : TStringContainer;
Strip : Boolean; { Strip symbols ? }
MakeLib : Boolean; { If unit : Make library ?}
ExeName, { FileName of the exe to be created }
LibName : String; { FileName of the lib to be created }
LinkResName : String[32]; { Name of response file }
LinkOptions : String; { Additional options to the linker }
LibrarySearchPath : String; { Where to look for libraries }
{ Methods }
Constructor Init;
Procedure SetFileName(const s:string);
function FindObjectFile(s : string) : string;
Procedure AddLibraryFile(S : String);
Procedure AddObjectFile(S : String);
Function FindLinker : String; { Find linker, sets Name }
Function DoExec(const command,para:string):boolean;
Function WriteResponseFile : Boolean;
Function Link:boolean;
Procedure Make_Library;
end;
PLinker=^TLinker;
Var Linker : TLinker;
Implementation
uses
Script,globals,systems,dos,verbose;
Constructor TLinker.Init;
begin
OFiles.Init;
LibFiles.Init;
OFiles.Doubles:=False;
LibFiles.Doubles:=False;
Strip:=false;
LinkOptions:='';
LinkResName:='link.res';
ExeName:='';
LibName:='';
{$ifdef linux}
LinkToC:=False;
LibrarySearchPath:='';
DynamicLinker:='/lib/ld-linux.so.1';
{$endif}
end;
Procedure TLinker.SetFileName(const s:string);
var
path:dirstr;
name:namestr;
ext:extstr;
begin
FSplit(s,path,name,ext);
LibName:=Path+Name+target_info.DllExt;
ExeName:=Path+Name+target_info.ExeExt;
end;
var
LastLDBin : string;
Function TLinker.FindLinker:string;
var
ldfound : boolean;
begin
if LastLDBin='' then
begin
if (target_info.target=target_WIN32) then
{ the win32 linker has another name to allow cross compiling between }
{ DOS and Win32, I think it should be possible to compile an ld }
{ with handles coff and pe, but I don't know how (FK) }
LastLDBin:=FindExe('ldw',ldfound)
else
LastLDBin:=FindExe('amigald',ldfound);
if (not ldfound) and (not externlink) then
begin
Message1(exec_w_linker_not_found,LastLDBin);
externlink:=true;
end;
if ldfound then
Message1(exec_u_using_linker,LastLDBin);
end;
FindLinker:=LastLDBin;
end;
{ searches an object file }
function TLinker.FindObjectFile(s:string) : string;
var
found : boolean;
begin
if pos('.',s)=0 then
s:=s+target_info.objext;
s:=FixFileName(s);
if FileExists(s) then
begin
Findobjectfile:=s;
exit;
end;
findobjectfile:=search(s,'.;'+unitsearchpath+';'+exepath,found)+s;
if (not externasm) and (not found) then
Message1(exec_e_objfile_not_found,s);
end;
Procedure TLInker.AddObjectFile (S : String);
begin
if pos('.',s)=0 then
s:=s+target_info.objext;
s:=FixFileName(s);
OFiles.Insert (S);
end;
Procedure TLInker.AddLibraryFile(S:String);
begin
if pos('.',s)=0 then
s:=s+target_info.dllext;
LibFiles.Insert (S);
end;
Function TLinker.DoExec(const command,para:string):boolean;
begin
DoExec:=true;
if not externlink then
begin
swapvectors;
exec(command,para);
swapvectors;
if (dosexitcode<>0) then
begin
Message(exec_w_error_while_linking);
DoExec:=false;
exit;
end
else
if (dosError<>0) then
begin
Message(exec_w_cant_call_linker);
ExternLink:=true;
end;
end;
if externlink then
AsmRes.AddLinkCommand (Command,Para,ExeName);
end;
Function TLinker.WriteResponseFile : Boolean;
Var
LinkResponse : Text;
i : longint;
prtobj,s : string;
begin
{ Open linkresponse and write header }
assign(linkresponse,inputdir+LinkResName);
rewrite(linkresponse);
{ Write Header and set runtime object (prt0) }
case target_info.target of
target_WIN32 : begin
prtobj:='';
writeln(linkresponse,'INPUT (');
end;
target_PalmOS:
begin
prtobj:='';
end;
target_linux : begin
if cs_profile in aktswitches then
prtobj:='gprt0'
else
prtobj:='prt0';
{$ifdef Linux}
if LinkToC then
writeln(linkresponse,'SEARCH_DIR ('+GCCLibraryPath +')');
{$endif}
writeln(linkresponse,'INPUT (');
end;
target_AMIGA: begin
prtobj:='prt0';
writeln(linkresponse,'INPUT (');
end;
else
prtobj:='prt0';
end;
{ add objectfiles, start with prt0 always }
if prtobj<>'' then
Writeln(linkresponse,FindObjectFile(prtobj));
while not OFiles.Empty do
begin
s:=Findobjectfile(OFiles.Get);
if s<>'' then
Writeln(linkresponse,s);
end;
{ Write libraries like -l<lib> }
While not LibFiles.Empty do
begin
S:=LibFiles.Get;
i:=Pos(target_info.dllext,S);
if i>0 then
Delete(S,i,255);
Writeln (LinkResponse,'-l'+S);
end;
{ Write End of response file }
if target_info.target in [target_WIN32,target_linux,target_AMIGA] then
Writeln (LinkResponse,')');
{ Close response }
close(linkresponse);
WriteResponseFile:=True;
end;
Function TLinker.link:boolean;
var
bindbin : string[80];
bindfound : boolean;
_stacksize,i,
_heapsize : longint;
s,s2 : string[10];
dummy : file;
success : boolean;
begin
{$ifdef linux}
if LinkToC then
begin
AddObjectFile('/usr/lib/crt0.o');
AddObjectFile(FindObjectFile('lprt'));
AddLibraryFile('libc.a');
AddLibraryFile('libgcc.a');
end;
{$endif Linux}
{ Create Linkoptions }
case target_info.target of
target_GO32V1:
LinkOptions:=LinkOptions+' -oformat coff-go32';
target_GO32V2:
LinkOptions:=LinkOptions+' -oformat coff-go32-exe';
target_linux: begin
if cs_profile in aktswitches then
begin
AddLibraryFile('gmon');
AddLibraryFile('c');
end;
end;
end;
{$ifdef linux}
If not LibFiles.Empty then
LinkOptions:='-dynamic-linker='+DynamicLinker+' '+LinkOptions;
{$endif linux}
if Strip then
LinkOptions:=LinkOptions+' -s';
{ Write used files and libraries }
WriteResponseFile;
{ Call linker }
if not externlink then
Message1(exec_i_linking,ExeName);
{$ifdef linux}
success:=DoExec(FindLinker,LinkOptions+' -o '+exename+' '+inputdir+LinkResName);
{$else}
if target_info.target in [target_WIN32,target_AMIGA] then
success:=DoExec(FindLinker,LinkOptions+' -o '+exename+' '+inputdir+